//
//  RootViewController.m
//  Feed Rider
//
//  Created by Adrian-Sergiu Nicuta on 17/09/11.
//  Copyright 2011 Adrisen Technologies SPRL. All rights reserved.
//

#import "RootViewController.h"
#import "Feed.h"
#import "AddFeedViewController.h"
#import "ViewFeedViewController.h"
#import "ImportSubscriptionsViewController.h"
#import "TempItem.h"
#import "FeedParseOperation.h"
#import "GTMNSString+HTML.h"
#import "FeedItemsConnectionDelegate.h"

@interface RootViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
@end

@implementation RootViewController

@synthesize fetchedResultsController = __fetchedResultsController;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize importFeedsConnection;
@synthesize subscriptionsData;
@synthesize adBannerView;
@synthesize feedsConnections;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Set up the edit and add buttons.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(insertNewObject)];
    self.navigationItem.rightBarButtonItem = addButton;
    [addButton release];
    
    feedsConnections = [[NSMutableDictionary alloc] init];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(mergeChanges:) name:NSManagedObjectContextDidSaveNotification object:nil];
    
    [self loadAllFeeds];
}

- (void)loadAllFeeds
{
    NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:@"Feed"];
    
    NSError *err = nil;
    NSArray *results = [self.managedObjectContext executeFetchRequest:req error:&err];
    [req release];
    
    for (Feed *feed in results) {
        FeedItemsConnectionDelegate *connectionDelegate = [[FeedItemsConnectionDelegate alloc] init];
        connectionDelegate.managedObjectContext = self.managedObjectContext;
        connectionDelegate.feedId = feed.objectID;
        connectionDelegate.rootViewController = self;
        
        NSURL *url = [NSURL URLWithString:feed.url];
        NSURLRequest *req = [NSURLRequest requestWithURL:url];
        NSURLConnection *feedConnection = [[NSURLConnection alloc] initWithRequest:req delegate:connectionDelegate startImmediately:YES];
        
        [feedsConnections setObject:feedConnection forKey:feed.url];
        [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
        [connectionDelegate release];
        [feedConnection release];
    }
}

- (void)deleteOldItems
{
    NSFetchRequest *req = [[NSFetchRequest alloc] initWithEntityName:@"Item"];
    
    NSDate *today = [NSDate date];
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *dateComponents = [[NSDateComponents alloc] init];
    [dateComponents setMonth:-6];
    NSDate *oldDate = [gregorian dateByAddingComponents:dateComponents toDate:today options:0];
    
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"updated <= %@ OR updated = $DATE", oldDate];
    predicate = [predicate predicateWithSubstitutionVariables:[NSDictionary dictionaryWithObject:[NSNull null] forKey:@"DATE"]];
    req.predicate = predicate;
    
    NSError *err = nil;
    NSArray *results = [self.managedObjectContext executeFetchRequest:req error:&err];
    
    [gregorian release];
    [dateComponents release];
    
    for (Item *oldItem in results) {
        if (!oldItem.read) {
            oldItem.feed.unreadCount = [NSNumber numberWithInt:oldItem.feed.unreadCount.intValue - 1];
        }
        [self.managedObjectContext deleteObject:oldItem];
    }
    
    [req release];
    
    NSError *error = nil;
    
    if(![self.managedObjectContext save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self deleteOldItems];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

}

- (void)viewWillDisappear:(BOOL)animated
{
	[super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated
{
	[super viewDidDisappear:animated];
}

/*
 // Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	// Return YES for supported orientations.
	return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
 */

// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        
        UILabel *titleLabel = [[[UILabel alloc] init] autorelease];
        titleLabel.tag = 1;
        titleLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        
        UILabel *countLabel = [[[UILabel alloc] init] autorelease];
        countLabel.tag = 2;
        countLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;

        [cell.contentView addSubview:titleLabel];
        [cell.contentView addSubview:countLabel];
    }

    // Configure the cell.
    [self configureCell:cell atIndexPath:indexPath];
    return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    const float kHeight = cell.bounds.size.height, kLeftIndent = 8.0, kOverallWidth = cell.bounds.size.width, kGap = 1.0;
    
    UILabel *titleLabel = (UILabel *)[cell.contentView viewWithTag:1];
    UILabel *countLabel = (UILabel *)[cell.contentView viewWithTag:2];
    
    Feed *feed = (Feed *)[self.fetchedResultsController objectAtIndexPath:indexPath];
    
    CGSize countSize = [[feed.unreadCount description] sizeWithFont:[countLabel font]];
    countSize.width = countSize.width + 24;
    const float countXPos = kOverallWidth - countSize.width;
    countLabel.frame = CGRectMake(countXPos, 0.0, countSize.width, kHeight);
    titleLabel.frame = CGRectMake(kLeftIndent, 0.0, countXPos - kLeftIndent - kGap, kHeight);
    
    titleLabel.text = feed.title;
    countLabel.text = [feed.unreadCount description];
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
{
	id <NSFetchedResultsSectionInfo> theSection = [[self.fetchedResultsController sections] objectAtIndex:section];

	return [theSection name];
}

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        // Delete the managed object for the given index path
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
        
        // Save the context.
        NSError *error = nil;
        if (![context save:&error])
        {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }   
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // The table view should not be re-orderable.
    return NO;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ViewFeedViewController *viewFeedViewController = [[ViewFeedViewController alloc] initWithNibName:@"ViewFeedViewController" bundle:nil];
    viewFeedViewController.managedObjectContext = self.managedObjectContext;
    
    Feed *selectedFeed = (Feed *)[self.fetchedResultsController objectAtIndexPath:indexPath];
    viewFeedViewController.CurrentFeed = selectedFeed;
    
    [self.navigationController pushViewController:viewFeedViewController animated:YES];
    
    [viewFeedViewController release];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Relinquish ownership any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload
{
    [self setAdBannerView:nil];
    [feedsConnections release];
    [super viewDidUnload];

    [[NSNotificationCenter defaultCenter] removeObserver:self forKeyPath:NSManagedObjectContextDidSaveNotification];
}

- (void)dealloc
{
    [__fetchedResultsController release];
    [__managedObjectContext release];
    [importFeedsConnection release];
    [feedsConnections release];
    
    [adBannerView release];
    [super dealloc];
}

- (void)insertNewObject
{
    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"Manage feeds" delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Import from Google reader", @"Add RSS feed", @"Refresh all", nil];
    actionSheet.actionSheetStyle = UIActionSheetStyleAutomatic;
    [actionSheet showInView:self.view];
    [actionSheet release];
}

#pragma mark - Action sheet

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 
{
    if (buttonIndex == 0) {
        ImportSubscriptionsViewController *view = [[ImportSubscriptionsViewController alloc] initWithNibName:@"ImportSubscriptionsViewController" bundle:nil];
        view.delegate = self;
        [self.navigationController presentModalViewController:view animated:YES];
        [view release];
    } else if (buttonIndex == 1) {
        AddFeedViewController *view = [[AddFeedViewController alloc] initWithNibName:@"AddFeedViewController" bundle:nil];
        view.fetchedResultsController = self.fetchedResultsController;
        [self.navigationController pushViewController:view animated:YES];
        [view release];
    } else if (buttonIndex == 2) {
        [self loadAllFeeds];
    }
}

- (void)importSubscriptionsViewController:(ImportSubscriptionsViewController *)importSubscriptionsController didEnterEmail:(NSString *)email andPassword:(NSString *)password
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
    
    NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.com/accounts/ClientLogin"]];
    
    NSData *postData = [[NSString stringWithFormat:@"Email=%@&Passwd=%@&source=OpenDocsClient1.0&service=reader&accountType=HOSTED_OR_GOOGLE", email, password] dataUsingEncoding:NSUTF8StringEncoding];
    [urlRequest addValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
    urlRequest.HTTPMethod = @"POST";
    urlRequest.HTTPBody = postData;
    
    self.subscriptionsData = [NSMutableData data];
    isRequestAuthActive = YES;
    NSURLConnection *aConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
    
    self.importFeedsConnection = aConnection;
    
    [aConnection release];
}

#pragma mark - URL connection delegate

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [subscriptionsData release];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.subscriptionsData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    if (isRequestAuthActive) {
        isRequestAuthActive = NO;
    
        NSMutableString *strData = [[[NSMutableString alloc] initWithData:subscriptionsData encoding:NSUTF8StringEncoding] autorelease];
        
        [self setSubscriptionsData:nil];
        
        NSScanner *scanner = [NSScanner scannerWithString:strData];
        if ([scanner scanUpToString:@"Auth=" intoString:NULL]) {
            [scanner scanString:@"Auth=" intoString:NULL];
            NSString *auth = nil;
            [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&auth];
                        
            NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://www.google.com/reader/api/0/subscription/list?output=json"]];
            [urlRequest addValue:@"3.0" forHTTPHeaderField:@"GData-Version"];
            [urlRequest addValue:[NSString stringWithFormat:@"GoogleLogin auth=%@", auth] forHTTPHeaderField:@"Authorization"];
            
            self.subscriptionsData = [NSMutableData data];
            isRequestSubscriptionsActive = YES;
            NSURLConnection *aConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
            
            self.importFeedsConnection = aConnection;
            
            [aConnection release];
        }
    } else if (isRequestSubscriptionsActive) {
        isRequestSubscriptionsActive = NO;
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        
        NSError *error = nil;
        
        NSDictionary *subscriptionsObject = [NSJSONSerialization JSONObjectWithData:subscriptionsData options:NSJSONReadingAllowFragments error:&error];
        
        if (subscriptionsObject) {
            NSArray *subscriptions = [subscriptionsObject objectForKey:@"subscriptions"];
            for (NSDictionary *subscription in subscriptions) {
                NSString *subscriptionUrl = nil;
                NSString *subscriptionId = [subscription objectForKey:@"id"];
                NSScanner *scanner = [NSScanner scannerWithString:subscriptionId];
                if ([scanner scanString:@"feed/" intoString:NULL]) {
                    [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&subscriptionUrl];
                
                    NSString *subscriptionTitle = [subscription objectForKey:@"title"];
                    NSArray *categories = [subscription objectForKey:@"categories"];
                    NSDictionary *category = [categories objectAtIndex:0];
                    NSString *categoryName = [category objectForKey:@"label"];
                    
                    Feed *newFeed = (Feed *)[NSEntityDescription insertNewObjectForEntityForName:@"Feed" inManagedObjectContext:self.managedObjectContext];
                    
                    newFeed.Title = subscriptionTitle;
                    newFeed.url = subscriptionUrl;
                    newFeed.Category = categoryName;
                    newFeed.unreadCount = [NSNumber numberWithInt:0];
                }
            }
            
            NSError *error = nil;
            
            if(![self.managedObjectContext save:&error]) {
                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
            
            [self loadAllFeeds];
        }
    }
}

#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController
{
    if (__fetchedResultsController != nil)
    {
        return __fetchedResultsController;
    }
    
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Feed" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    
    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];
    
    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"category" ascending:YES];
    NSSortDescriptor *sortDescriptor2 = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil];
    
    [fetchRequest setSortDescriptors:sortDescriptors];
    
    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"category" cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
    
    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor1 release];
    [sortDescriptor2 release];
    [sortDescriptors release];

	NSError *error = nil;
	if (![self.fetchedResultsController performFetch:&error])
    {
	    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
	    abort();
	}
    
    return __fetchedResultsController;
}

#pragma mark - Fetched results controller delegate

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch(type)
    {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
            
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;
    
    switch(type)
    {
            
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
            
        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
            
        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;
            
        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
    return YES;
}

#pragma mark - AD Banner View Delegate

- (void)bannerView:(ADBannerView *)banner didFailToReceiveAdWithError:(NSError *)error
{
    
}

#pragma mark - Notification Center

- (void)mergeChanges:(NSNotification *)notification 
{
    if (notification.object != self.managedObjectContext) {
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
    }
}

@end
